home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / c / nos042_s / pathname.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  4KB  |  161 lines

  1. /* Convert relative to absolute pathnames
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4.  
  5. /****************************************************************************
  6. *    09 Jun 92    1.2        GT    MS-DOS: watch out for <drive>:<path>.            *
  7. ****************************************************************************/
  8.  
  9. #include <stdio.h>
  10. #include "global.h"
  11. #include "dirutil.h"
  12.  
  13. static void crunch __ARGS((char *buf,char *path));
  14.  
  15. /* Given a working directory and an arbitrary pathname, resolve them into
  16.  * an absolute pathname. Memory is allocated for the result, which
  17.  * the caller must free
  18.  */
  19. char *
  20. pathname(cd,path)
  21. char *cd;    /* Current working directory */
  22. char *path;    /* Pathname argument */
  23. {
  24.     register char *buf;
  25. #if defined(MSDOS) || defined(ATARI)
  26.     char *cp,c;
  27.     char *tbuf;
  28.     int tflag = 0;
  29. #ifdef MSDOS
  30.     char *path_ptr;                            /* -> path component            */
  31. #endif
  32. #endif
  33.  
  34.     if(cd == NULLCHAR || path == NULLCHAR)
  35.         return NULLCHAR;
  36.  
  37. #if defined(MSDOS) || defined(ATARI)
  38.     /* If path has any backslashes, make a local copy with them
  39.      * translated into forward slashes
  40.      */
  41.     if(strchr(path,'\\') != NULLCHAR){
  42.         tflag = 1;
  43.         cp = tbuf = mallocw(strlen(path));
  44.         while((c = *path++) != '\0'){
  45.             if(c == '\\')
  46.                 *cp++ = '/';
  47.             else
  48.                 *cp++ = c;
  49.         }
  50.         *cp = '\0';
  51.         path = tbuf;
  52.     }
  53. #endif
  54.  
  55.     /* Strip any leading white space on args */
  56.     while(*cd == ' ' || *cd == '\t')
  57.         cd++;
  58.     while(*path == ' ' || *path == '\t')
  59.         path++;
  60.  
  61.     /* Allocate and initialize output buffer; user must free */
  62.     buf = mallocw((unsigned)strlen(cd) + strlen(path) + 10);    /* fudge factor */
  63.     buf[0] = '\0';
  64.  
  65. /* Interpret path relative to cd only if it doesn't begin with "/" */
  66.  
  67. #if defined(MSDOS) || defined(ATARI)
  68.     if (path[0] != '/' && path[1] != ':')
  69. #else
  70.     if (path[0] != '/') 
  71. #endif
  72.         crunch(buf,cd);
  73.  
  74. #if defined(MSDOS) /* || defined(ATARI) */
  75.     if (path[1] == ':')
  76.         path_ptr = &path[2];
  77.     else
  78.         path_ptr = path;
  79.  
  80.     crunch (buf, path_ptr);
  81. #else
  82.     crunch(buf,path);
  83. #endif
  84.  
  85.     /* Special case: null final path means the root directory */
  86.     if(buf[0] == '\0'){
  87.         buf[0] = '/';
  88.         buf[1] = '\0';
  89.     }
  90. #if defined(MSDOS) || defined(ATARI)
  91.     if(tflag)
  92.         free(tbuf);
  93. #endif
  94.     return buf;
  95. }
  96.  
  97. /* Process a path name string, starting with and adding to
  98.  * the existing buffer
  99.  */
  100. static void
  101. crunch(buf,path)
  102. char *buf;
  103. register char *path;
  104. {
  105.     register char *cp;
  106.  
  107. #if defined(MSDOS) || defined(ATARI)
  108.     /* If <path> starts with "<drive>:", nail that into the buffer first. */
  109.  
  110.     if (*buf == '\0' && path[1] == ':')
  111.         {
  112.         *buf++ = *path++;
  113.         *buf++ = *path++;
  114.         *buf = '\0';
  115.         }
  116.     else if (path[1] == ':')
  117.         {
  118.         /* Something already in buffer - skip drive. */
  119.         
  120.         path += 2;
  121.         }
  122. #endif
  123.  
  124.     cp = buf + strlen(buf);    /* Start write at end of current buffer */
  125.     
  126.     /* Now start crunching the pathname argument */
  127.     for(;;){
  128.         /* Strip leading /'s; one will be written later */
  129.         while(*path == '/')
  130.             path++;
  131.         if(*path == '\0')
  132.             break;        /* no more, all done */
  133.         /* Look for parent directory references, either at the end
  134.          * of the path or imbedded in it
  135.          */
  136.         if(strcmp(path,"..") == 0 || strncmp(path,"../",3) == 0){
  137.             /* Hop up a level */
  138.             if((cp = strrchr(buf,'/')) == NULLCHAR)
  139.                 cp = buf;    /* Don't back up beyond root */
  140.             *cp = '\0';        /* In case there's another .. */
  141.             path += 2;        /* Skip ".." */
  142.             while(*path == '/')    /* Skip one or more slashes */
  143.                 path++;
  144.         /* Look for current directory references, either at the end
  145.          * of the path or imbedded in it
  146.          */
  147.         } else if(strcmp(path,".") == 0 || strncmp(path,"./",2) == 0){
  148.             /* "no op" */
  149.             path++;            /* Skip "." */
  150.             while(*path == '/')    /* Skip one or more slashes */
  151.                 path++;
  152.         } else {
  153.             /* Ordinary name, copy up to next '/' or end of path */
  154.             *cp++ = '/';
  155.             while(*path != '/' && *path != '\0')
  156.                 *cp++ = *path++;
  157.         }
  158.     }
  159.     *cp++ = '\0';
  160. }
  161.